package com.example.base.system.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.base.app.AppInfo;
import com.example.base.app.AppSecretInfo;
import com.example.base.config.ConfigService;
import com.example.base.excetion.GlobalExcetion;
import com.example.base.system.SysAppService;
import com.example.base.system.domain.SysApp;
import com.example.base.system.domain.vo.SysAppVo;
import com.example.base.system.mapper.SysAppMapper;
import com.example.base.utils.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.cache.annotation.*;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.cache.annotation.CacheConfig;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.Serializable;
import java.net.URLClassLoader;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author X.I.O
 * @since 2024-02-23
 */
@Slf4j
@Service
@Transactional
@CacheConfig(cacheNames = "SysAppServiceImpl")
public class SysAppServiceImpl extends ServiceImpl<SysAppMapper, SysApp> implements SysAppService {

    private volatile Map<String,SysApp> MapApp;

    @Cacheable(cacheNames = "sysapp",key = "#id")
    @Override
    public SysApp getById(Serializable id){
        return super.getById(id);
    }

    @CacheEvict(cacheNames = "sysapp", key = "#id")
    @Override
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

    @CacheEvict(cacheNames = "sysapp", key = "#sysapp.id")
    @Override
    public boolean updateById(SysApp sysapp) {
        return super.updateById(sysapp);
    }

    @CachePut(cacheNames = "sysapp", key = "#sysapp.id")
    public SysApp saveSysApp(SysApp sysapp) throws GlobalExcetion {
        super.save(sysapp);
        return sysapp;
    }

    @CacheEvict(cacheNames = "sysapp", key = "#sysapp.id")
    public SysApp updateSysAppById(SysApp sysapp) throws GlobalExcetion{
        super.updateById(sysapp);
        return sysapp;
    }


    public SysApp saveOrUpdateSysApp(SysAppVo sysappVo) throws GlobalExcetion{
        SysApp sysapp=new SysApp();
        BeanUtils.copyProperties(sysappVo,sysapp);
        if(sysappVo.getId()!=null){
            SysApp sysappEntity=super.baseMapper.selectById(sysappVo.getId());
            if(sysappEntity==null){
                throw new GlobalExcetion(1,"数据不存在");
            }
            super.baseMapper.updateById(sysapp);
        }else{
            super.baseMapper.insert(sysapp);
        }
        return sysapp;
    }

    public IPage<SysApp> page(Integer page, Integer pageSize) throws GlobalExcetion{
        LambdaQueryWrapper<SysApp> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        IPage<SysApp> iPage=super.baseMapper.selectPage(new Page(page,pageSize),lambdaQueryWrapper);
        return iPage;
    }

    @Override
    public void operateSysApp(File file, AppInfo appInfo, AppSecretInfo info) {
        String fileName=file.getName();
        SysApp sysApp=getSysAppByFileName(fileName);
        if(this.MapApp==null){
            this.MapApp=new ConcurrentHashMap<>();
        }
        if(sysApp==null){
            SysApp app=new SysApp();
            app.setAppFilename(fileName);
            app.setAppPath(file.getPath());
            app.setAppRunStartdatetime(new Date());
            app.setCreatetime(new Date());
            app.setAppUpdatetime(new Date());
            app.setAppName(appInfo.getAppName());
            app.setAppStatus(true);
            app.setAppSecretkey(appInfo.getAppSecret());
            app.setAppExpiredate(info.getExpireDate());
            app.setAppInfo(appInfo);
            super.save(app);
            this.MapApp.put(app.getAppName(),app);
        }else {
            sysApp.setAppName(appInfo.getAppName());
            sysApp.setAppSecretkey(appInfo.getAppSecret());
            sysApp.setAppRunStartdatetime(new Date());
            sysApp.setAppUpdatetime(new Date());
            sysApp.setAppName(appInfo.getAppName());
            sysApp.setAppPath(file.getPath());
            sysApp.setAppStatus(true);
            sysApp.setAppExpiredate(info.getExpireDate());
            sysApp.setAppInfo(appInfo);
            super.updateById(sysApp);
            this.MapApp.put(sysApp.getAppName(),sysApp);
        }
    }

    @Override
    public List<SysApp> getSysAppList() {
        if(this.MapApp==null){
            return Collections.EMPTY_LIST;
        }
        List<SysApp> list = new ArrayList<>(this.MapApp.values());
        return list;
    }

    @Override
    public SysApp getSysAppByAppName(String appName) {
        if(this.MapApp==null){
            return null;
        }
        return this.MapApp.get(appName);
    }

    @Override
    public SysApp getSysApp(HttpServletRequest request) {
        String url=request.getRequestURI();
        String appName=extractAppName(url);
        if(this.MapApp==null){
            return null;
        }
        return this.MapApp.get(appName);
    }

    private String extractAppName(String input) {
        String[] parts = input.split("/");
        if (parts.length >= 3) {
            return parts[2];
        } else {
            return "未找到AppName";
        }
    }

    @Override
    public void flushSysApp(String appName, SysApp sysApp) {
        if(this.MapApp!=null){
            if(this.MapApp.containsKey(appName)){
                this.MapApp.put(appName,sysApp);
                this.updateById(sysApp);
            }
        }
    }

    @Override
    public void sysAppStrat(String fileName) {
        if(this.MapApp!=null){
            for(SysApp sysApp:this.MapApp.values()){
                if(sysApp.getAppFilename().equals(fileName)){
                    sysApp.setAppStatus(false);
                }
            }
        }
    }

    @Override
    public void sysAppEnd(String fileName) {
        if(this.MapApp!=null){
            for(SysApp sysApp:this.MapApp.values()){
                if(sysApp.getAppFilename().equals(fileName)){
                    sysApp.setAppStatus(true);
                }
            }
        }
    }


    @Override
    public SysApp getSysAppByFileName(String fileName) {
        LambdaQueryWrapper<SysApp> sysAppLambdaQueryWrapper=new LambdaQueryWrapper<>();
        sysAppLambdaQueryWrapper.eq(SysApp::getAppFilename,fileName);
        SysApp sysApp=super.baseMapper.selectOne(sysAppLambdaQueryWrapper);
        return sysApp;
    }

    @Value("${watch.path}")
    private String watchPath;

    @Autowired
    private ConfigService configService;

    @Override
    public String getAppPath() {
        String appPath=configService.getSysConfigByKey("app_path");
        if(StringUtils.isNotBlank(appPath)){
            File file=new File(appPath);
            if(file.exists()){
                return file.getPath();
            }
        }
        String path= FileUtils.getSystemPath();
        if(!StringUtils.isNotBlank(watchPath)){
            watchPath="app_out";
        }
        final File file = new File(path+File.separator+watchPath);
        if(!file.exists()){
            file.mkdirs();
        }
        return file.getPath();
    }

}
